﻿using Quartz;
using RuoVea.ExDto;
using RuoVea.ExEnum;
using RuoVea.ExUtil;
using RuoVea.QuartzNetUI.Entitys;
using RuoVea.QuartzNetUI.Server;
using RuoVea.QuartzNetUI.Server.Dto;
using RuoVea.QuartzNetUI.Server.Enums;
using System.Net.Http;
using System.Security.Authentication;
using System.Text;

namespace RuoVea.QuartzNetUI
{
    /// <summary>
    /// 基础Job 继承来自IJob 继承实现该类带自动日志记录
    /// </summary>   
    public abstract class BaseJob : IJob
    {
        private readonly ITaskLogService _tasksQzLogService;
        /// <summary>
        /// 初始化构造函数
        /// </summary>
        /// <param name="tasksQzLogService"></param>
        public BaseJob(ITaskLogService tasksQzLogService)
        {
            _tasksQzLogService = tasksQzLogService;
        }
        //public abstract Task ExecSomethingAsync(IJobExecutionContext context);
        /// <summary>
        /// 被重写实现方法
        /// </summary>
        /// <param name="jobData"></param>
        /// <returns></returns>
        public abstract Task<RestfulResult> ExecSomethingAsync(TaskDetailInDto jobData);
        /// <summary>
        /// 执行的函数方法
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Execute(IJobExecutionContext context)
        {
            RequestTypeEnum runType = context.JobDetail.JobDataMap.GetRunType();
            var stopwatch = Common.TimerStart();
            //context.JobDetail.JobDataMap.TryGetValue(ConstantDefine.RunType, out runType);
            if (runType >= 0)
            {
                TaskLog tasksLog = new TaskLog { Status = YesOrNot.N, };
                tasksLog.Insert();
                TaskDetailInDto taskDetail = new TaskDetailInDto();
                try
                {
                    taskDetail = context.JobDetail.JobDataMap.GetJobData();

                    tasksLog.JobId = taskDetail.Id;
                    tasksLog.SchedName = taskDetail.SchedName;
                    tasksLog.JobName = taskDetail.JobName;
                    tasksLog.JobGroup = taskDetail.JobGroup;
                    tasksLog.RunType = taskDetail.RunType.ToString();
                    tasksLog.BeginTime = DateTime.Now.ToDateTimeString();
                    tasksLog.Parameters = taskDetail.Parameters;
                    //tasksLog.Result
                    if (runType == RequestTypeEnum.Run)
                        tasksLog.JobAddress = taskDetail.AssemblyName + "." + taskDetail.ClassName;
                    else
                        tasksLog.JobAddress = taskDetail.RequestUrl;

                    RestfulResult restfulResult = await ExecSomethingAsync(taskDetail);

                    if (restfulResult.Code == CodeStatus.OK)
                    {
                        tasksLog.Status = YesOrNot.Y;
                        tasksLog.Result = restfulResult.Data?.Json2Str();
                        // send mail,workweixin
                        await SendMessage(SendMsgTypeEnum.OK, taskDetail, tasksLog.Result);
                    }
                    else
                    {
                        tasksLog.Status = YesOrNot.N;
                        tasksLog.Exception = restfulResult.Message;
                        // send mail,workweixin
                        await SendMessage(SendMsgTypeEnum.Err, taskDetail, tasksLog.Exception);
                    }
                }
                catch (Exception ex)
                {
                    tasksLog.Status = YesOrNot.N;
                    tasksLog.Exception = (new { Source = ex.Source, StackTrace = ex.StackTrace, Message = ex.Message }).Json2Str();
                    context.JobDetail.JobDataMap.SetLastException(tasksLog.Exception);
                    tasksLog.Exception.WriteErrorLine();
                    // send mail,workweixin
                    await SendMessage(SendMsgTypeEnum.Err, taskDetail, tasksLog.Exception);
                }
                finally
                {
                    stopwatch.Stop();
                    tasksLog.EndTime = DateTime.Now.ToDateTimeString();
                    tasksLog.Elapsed = Common.TimerEnd(stopwatch);
                    var result = await _tasksQzLogService.InsertAsync(tasksLog);
                    // send mail,workweixin
                    await SendMessage(SendMsgTypeEnum.All, taskDetail);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="typeEnum"></param>
        /// <param name="data"></param>
        /// <param name="magContent"></param>
        /// <returns></returns>
        private async Task SendMessage(SendMsgTypeEnum typeEnum, TaskDetailInDto data,string magContent=null)
        {
            if (data == null) return;
            try {

                if (!string.IsNullOrWhiteSpace(magContent) && magContent.Length > 400)
                {
                    ("发送的消息太长(超出400)为：" + magContent).WriteInfoLine();
                    magContent = magContent.Substring(0, 400);
                }

                if (typeEnum == data.MailMsgType) 
                    SendMailMessage(data,   magContent );

                if (typeEnum == data.HorkMsgType)
                    await SendHorkMessage(data,magContent);
            }
            catch (Exception ex)
            {
                ex.Message.WriteErrorLine();
            }
        }
        /// <summary>
        /// 发送邮箱
        /// </summary>
        /// <param name="data"></param>
        /// <param name="magContent"></param>
        /// <returns></returns>
        private void SendMailMessage(TaskDetailInDto data, string magContent = null) { 
        
        }
        /// <summary>
        /// 发送机器人
        /// </summary>
        /// <param name="data"></param>
        /// <param name="magContent"></param>
        /// <returns></returns>
        private async Task SendHorkMessage(TaskDetailInDto data, string magContent = null) {
            var content = new StringContent($@"{{""msgtype"": ""markdown"", ""markdown"": {{""content"": ""{magContent}""}}}}", Encoding.UTF8, "application/json");

            HttpClientHandler handler = new HttpClientHandler();
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.ServerCertificateCustomValidationCallback += (sender, cert, chain, sslPolicyErrors) => { return true; };
            handler.SslProtocols = SslProtocols.None;
            var response =await HttpUtils.HttpPostAsync(data.HorkUrl, content.ToString());
            response.WriteWarningLine();
        }
    }
}
